package com.china.produce.controller;

import cn.hutool.core.convert.Convert;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @ClassName
 * @Author niujie
 * @Version
 * @Description
 * @CreateTime 2022/5/18
 */
@RestController
@RequestMapping("/thread")
public class ThreadController {

    @Autowired
    @Qualifier("thread-pool-task")
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

//    @Autowired
//    private ThreadPoolExecutor threadPoolExecutor;

    private static  ExecutorService pool;


//    @PostMapping("/test")
//    public String test() {
//        for (int i = 0; i < 4; i++) {
//            threadPoolExecutor.execute(new Runnable() {
//                @Override
//                public void run() {
//                    try {
//                        Thread.sleep(1000);
//                    }
//                    catch (InterruptedException e)
//                    {
//                        e.printStackTrace();
//                    }
//                    System.out.println("thread name:"+Thread.currentThread().getName()+",执行:");
//                }
//            });
//        }
//
//        try {
//            ArrayList<Future> futures = new ArrayList<>();
//            for (int i = 0; i < 3; i++) {
//                Future<String> future = threadPoolExecutor.submit(new sendCallable("hello" + i));
//                futures.add(future);
//            }
//            for (Future future : futures) {
//                System.out.println(future.get());
//            }
//        }catch (Exception e) {
//            e.printStackTrace();
//        }
//
//
//        return "success";
//    }

    @GetMapping("/await")
    public void await() {
        ExecutorService executor = new ThreadPoolExecutor(4, 8, 120, TimeUnit.SECONDS, new LinkedBlockingQueue<>());

        ArrayList<Future<Boolean>> futures = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Future<Boolean> future = executor.submit(new sendMessageTask("test"));
            futures.add(future);
        }
        executor.shutdown();
        try {
            if (executor.awaitTermination(3, TimeUnit.HOURS)) {
                for (int i = 0; i < futures.size(); i++) {
                    Future<Boolean> future = futures.get(i);
                    System.out.println(future.get());
                }
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    @GetMapping("/callableExecute")
    public void execute() throws InterruptedException, ExecutionException {
        String[] a = {"hao", "xue", "xia", "nanjing", "shenzhen", "shanghai",
                "hao2", "xue2", "xia2", "nanjing2", "shenzhen2", "shanghai2",
                "hao3", "xue3"};

        List<String> strings = Convert.toList(String.class, a);

        ArrayList<Future<String>> futures = new ArrayList<>();

        for (String string : strings) {
            Future<String> future = threadPoolTaskExecutor.submit(new sendCallable(string));
            futures.add(future);
        }


        for (Future<String> future : futures) {
            System.out.println(":" + future.get());
        }

    }

    @GetMapping("/linkBlockQueue")
    public Boolean testLinkedBlockingQueue()
    {
        //使用无界任务队列，线程池的任务队列可以无限制的添加新的任务，而线程池创建的最大线程数量就是你corePoolSize设置的数量，
        pool = new ThreadPoolExecutor(3, 3, 1000, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
        for(int i = 0; i < 30; i++) {
            pool.execute(new ThreadTask());
        }

        return true;
    }

    @GetMapping("/priorityBlockingQueue")
    public Boolean priorityBlockingQueue()
    {
        //优先任务队列
        pool = new ThreadPoolExecutor(1, 2, 1000, TimeUnit.MILLISECONDS, new PriorityBlockingQueue<Runnable>(),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());

        for(int i = 0; i < 20; i++) {
            pool.execute(new ThreadTaskes(i));
        }

        return true;
    }

    @GetMapping("/queryBlockingSubmit")
    public Boolean queryBlockingSubmit() throws ExecutionException, InterruptedException {
        ArrayList<Future<Boolean>> objects = new ArrayList<>();

        pool = new ThreadPoolExecutor(1, 2, 1000, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());

        for (int i = 0; i < 10; i++) {
            Future<Boolean> future = pool.submit(new sendMessageTask("好好的"));

            objects.add(future);
        }

        pool.shutdown();

        for (int i = 0; i < objects.size(); i++) {
            System.out.println(objects.get(i).get());
        }

        return true;
    }

    class sendCallable implements Callable<String> {

        private String msg;

        public sendCallable(String msg) {
            this.msg = msg;
        }

        @Override
        public String call() throws Exception {

            System.out.println(Thread.currentThread().getName() + " 开始了 ");

            Thread.sleep(5000);

            System.out.println(Thread.currentThread().getName() + " 结束了 ");

            return msg;
        }
    }

    static class sendMessageTask implements Callable<Boolean>{

        private String msg;

        private sendMessageTask(String msg)
        {
            this.msg = msg;
        }

        @Override
        public Boolean call() throws Exception {

            Thread.sleep(1000);

            System.out.println(msg);

            return true;
        }
    }

    static class ThreadTaskes implements Runnable, Comparable<ThreadTaskes>{

        private int priority;

        public ThreadTaskes(int priority)
        {
            this.priority = priority;
        }

        public int compareTo(ThreadTaskes o)
        {
            return  this.priority > o.priority ? -1 : 1;
        }

        @Override
        public void run() {
            try {
                //让线程阻塞，使后续任务进入缓存队列
                Thread.sleep(1000);
                System.out.println("priority:"+this.priority+",ThreadName:"+Thread.currentThread().getName());
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    static class  ThreadTask implements Runnable{
        public ThreadTask() {
        }
        @SneakyThrows
        public void run() {
            Thread.sleep(3000);
            System.out.println(Thread.currentThread().getName());
        }
    }

    static class NewTask implements Runnable {
        private String name;

        public  NewTask(String name) {

            this.name = name;
        }

        @Override
        public void run() {
            try {
                Long duration = (long) (Math.random() * 10);
                System.out.println("Executing : " + name);
                TimeUnit.SECONDS.sleep(duration);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


